//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
// Port Registers for M8051W/EW
// 
// $Log: m3s014dy.v,v $
// Revision 1.4  2001/11/20
// First checkin of version 2 features and name change
//
// Revision 1.2  2001/10/31
// First parsable verilog for EW
//
// Revision 1.1.1.1  2001/07/17
// Re-imported E-Warp from Farnham filesystem
//
// Revision 1.3  2000/10/24
// Multiplier rewritten to improve power consumption.
// Code changes for Leonardo (ECN01372).
// Code changes for formal verification tools (ECN01410).
// MOVX @Ri page address controllable from PORT2I if I/O ports ommitted (ECN01387).
//
// Revision 1.2  2000/02/05
// Name change repercussions
//
// Revision 1.1.1.1  1999/10/28
// "initialization and source check-in for m8051e"
//
// Revision 1.1  1999/10/22
// Initial revision
//
////////////////////////////////////////////////////////////////////////////////

`include "m8051w_defs.v"

module m3s014dy (PORTS_SFR_DATA, NPORT1E, NPORT2E, NPORT3E,
//*******************************************************************       //
//IMPORTANT NOTICE                                                          //
//================                                                          //
//Copyright Mentor Graphics Corporation 1996 - 1999.  All rights reserved.  //
//This file and associated deliverables are the trade secrets,              //
//confidential information and copyrighted works of Mentor Graphics         //
//Corporation and its licensors and are subject to your license agreement   //
//with Mentor Graphics Corporation.                                         //
//                                                                          //
//Use of these deliverables for the purpose of making silicon from an IC    //
//design is limited to the terms and conditions of your license agreement   //
//with Mentor Graphics If you have further questions please contact Mentor  //
//Graphics Customer Support.                                                //
//                                                                          //
//This Mentor Graphics core (m8051w v2002.080) was extracted on             //
//workstation hostid 8316cbec Inventra                                      //
                 PORT0O, PORT1O, PORT2O, PORT3O,
                 PORT0I, PORT1I, PORT2I, PORT3I, SFRWE, REG_RESULT,
                 DESTIN_ADDR, SFRSA, PORT_CON, INTERNAL_RESET, STATE, CCLK);

  output [7:0] PORTS_SFR_DATA;
  output [7:0] PORT0O, PORT1O, PORT2O, PORT3O;
  output [7:0] NPORT1E, NPORT2E, NPORT3E;

  input  [7:0] PORT0I, PORT1I, PORT2I, PORT3I;
  input        SFRWE;
  input  [7:0] REG_RESULT;
  input  [6:0] DESTIN_ADDR;
  input  [6:0] SFRSA;
  input        PORT_CON, INTERNAL_RESET;
  input  [0:0] STATE;
  input        CCLK;
  
  reg    [7:0] PORT_0, PORT_1, PORT_2, PORT_3;
  reg    [7:0] PORTS_SFR_DATA;
  reg    [7:0] PORT_0_SFR, PORT_1_SFR, PORT_2_SFR, PORT_3_SFR;     // Port SFRs
  reg    [7:0] NPORT1E, NPORT2E, NPORT3E;               // output drive enables
  reg    [7:0] PORT_0_SAMPLE, PORT_1_SAMPLE, PORT_2_SAMPLE, PORT_3_SAMPLE;

  wire         PORT_0_WRITE, PORT_1_WRITE, PORT_2_WRITE, PORT_3_WRITE; 

  assign PORT_0_WRITE = SFRWE && DESTIN_ADDR[6:0] == `AddrP0;
  assign PORT_1_WRITE = SFRWE && DESTIN_ADDR[6:0] == `AddrP1;
  assign PORT_2_WRITE = SFRWE && DESTIN_ADDR[6:0] == `AddrP2;
  assign PORT_3_WRITE = SFRWE && DESTIN_ADDR[6:0] == `AddrP3;

  // Port SFRs

  always @(posedge CCLK)
  begin: p_port_regs
    if (INTERNAL_RESET) begin
      PORT_0_SFR <= 8'hff;
      PORT_1_SFR <= 8'hff;
      PORT_2_SFR <= 8'hff;
      PORT_3_SFR <= 8'hff;
    end
    else begin
      if (PORT_0_WRITE) PORT_0_SFR <= REG_RESULT;
      if (PORT_1_WRITE) PORT_1_SFR <= REG_RESULT;
      if (PORT_2_WRITE) PORT_2_SFR <= REG_RESULT;
      if (PORT_3_WRITE) PORT_3_SFR <= REG_RESULT;
    end
  end

  // Port driver cell enables active for output in low state and for one clock
  // cycle following a zero-to-one transition of the port output.

  always @(posedge CCLK)
  begin: p_port_enables
    if (INTERNAL_RESET) begin
      NPORT1E <= 8'hff;
      NPORT2E <= 8'hff;
      NPORT3E <= 8'hff;
    end
    else begin
      NPORT1E <= PORT_1_WRITE? REG_RESULT & PORT1O: PORT1O;
      NPORT2E <= PORT_2_WRITE? REG_RESULT & PORT2O: PORT2O;
      NPORT3E <= PORT_3_WRITE? REG_RESULT & PORT3O: PORT3O;
    end
  end

  // Ports are sampled at end of phase two for correct core operation during
  // multicycle instructions.

  always @(posedge CCLK)
  begin: p_port_samplers
    if (STATE[0]) begin
      PORT_0_SAMPLE <= PORT0I;
      PORT_1_SAMPLE <= PORT1I;
      PORT_2_SAMPLE <= PORT2I;
      PORT_3_SAMPLE <= PORT3I;
    end
  end

  // Read-modify-write source multiplexer
  // When PORT_CON is set the instruction is a read-modify-write operation and
  // so the SFR flip-flops are read instead of the port input pins. 

  always @(PORT_0_SAMPLE or PORT_1_SAMPLE or PORT_2_SAMPLE or PORT_3_SAMPLE or
           PORT_0_SFR or PORT_1_SFR or PORT_2_SFR or PORT_3_SFR or PORT_CON)
  begin: p_rmw_data
    if (PORT_CON) begin
      PORT_0 <= PORT_0_SFR;
      PORT_1 <= PORT_1_SFR;
      PORT_2 <= PORT_2_SFR;
      PORT_3 <= PORT_3_SFR;
    end
    else begin
      PORT_0 <= PORT_0_SAMPLE;
      PORT_1 <= PORT_1_SAMPLE;
      PORT_2 <= PORT_2_SAMPLE;
      PORT_3 <= PORT_3_SAMPLE;
    end
  end

  assign PORT0O = PORT_0_SFR;
  assign PORT1O = PORT_1_SFR;
  assign PORT2O = PORT_2_SFR;
  assign PORT3O = PORT_3_SFR;

  // SFR Data Multiplexer
  always @(PORT_0 or PORT_1 or PORT_2 or PORT_3 or SFRSA)
  begin: p_sfr_mux
    case(SFRSA)
      `AddrP0: PORTS_SFR_DATA = PORT_0;
      `AddrP1: PORTS_SFR_DATA = PORT_1;
      `AddrP2: PORTS_SFR_DATA = PORT_2;
      `AddrP3: PORTS_SFR_DATA = PORT_3;
      default: PORTS_SFR_DATA = 0;
    endcase
  end

endmodule
